package com.mikgonz.farkle.ui;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;

import com.markupartist.android.widget.ActionBar;
import com.markupartist.android.widget.ActionBar.IntentAction;
import com.mikgonz.farkle.AsyncRPC;
import com.mikgonz.farkle.R;
import com.mikgonz.farkle.Util;
import com.mikgonz.farkle.shared.UserProxy;

public class OnlineAccount extends Activity implements
		DialogInterface.OnClickListener, OnKeyListener, OnEditorActionListener,
		OnCancelListener {

	private final static int WAIT_DIALOG = 6;
	private final static int PROMPT_DIALOG = 5;

	private SharedPreferences prefs;

	private Button saveBtn;
	private Button checkBtn;
	private EditText userNameBox;
	private EditText passwordBox;

	private boolean showDialog = true;
	private NewTask task;

	private String id;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.account_details);

		prefs = PreferenceManager.getDefaultSharedPreferences(this);

		saveBtn = (Button) findViewById(R.id.save_button);
		userNameBox = (EditText) findViewById(R.id.username_edit_text);
		passwordBox = (EditText) findViewById(R.id.password_edit_text);
		checkBtn = (Button) findViewById(R.id.check_button);
		task = new NewTask(OnlineAccount.this);

		restoreState(savedInstanceState);

		if (showDialog) {
			final Bundle args = new Bundle();
			args.putBoolean(Util.TO_LISTEN, true);
			showDialog(PROMPT_DIALOG, args);
		}

		setUpBar();

		userNameBox.setOnKeyListener(this);
		userNameBox.setOnEditorActionListener(this);
		passwordBox.setOnKeyListener(this);
		passwordBox.setOnEditorActionListener(this);

	}

	private void restoreState(Bundle savedInstanceState) {
		if (savedInstanceState == null
				|| !savedInstanceState.getBoolean("hasState"))
			return;

		checkBtn.setEnabled(savedInstanceState.getBoolean("availState"));
		saveBtn.setText(savedInstanceState.getCharSequence("saveText"));

		userNameBox.setText(savedInstanceState.getCharSequence("userName"));
		passwordBox.setText(savedInstanceState.getCharSequence("password"));

		showDialog = savedInstanceState.getBoolean("showDialog");

	}

	private void setUpBar() {
		ActionBar bar = (ActionBar) findViewById(R.id.actionbar);

		Intent restart = new Intent(this, Main.class);
		restart.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| Intent.FLAG_ACTIVITY_CLEAR_TOP);
		bar.setHomeAction(new IntentAction(this, restart, R.drawable.house));
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		outState.putBoolean("hasState", true);
		// Determined by AlertDialog
		outState.putBoolean("availState", checkBtn.isEnabled());
		outState.putCharSequence("saveText", saveBtn.getText());

		// Transfer Contents of EditText's
		outState.putCharSequence("userName", userNameBox.getText().toString());
		outState.putCharSequence("password", passwordBox.getText().toString());

		// Remember to the dialog should show or not
		outState.putBoolean("showDialog", showDialog);

		super.onSaveInstanceState(outState);
	}

	public void onSave(View v) {

		// Ask to populate
		if (userNameBox.getText().length() == 0
				|| passwordBox.getText().length() == 0) {
			Toast.makeText(getApplicationContext(),
					"Please enter a Username and Password", Toast.LENGTH_SHORT)
					.show();
			return;
		}

		String username = userNameBox.getText().toString().toLowerCase().trim();
		String password = passwordBox.getText().toString();
		String xtifyKey = prefs.getString(Util.PREF_XTIFYKEY, null);
		if (xtifyKey == null) {
			Log.w(getClass().getName(), "NO XTIFYKEY!");
			return;
		}

		id = prefs.getString(Util.PREF_USERID, null);

		if (checkBtn.isEnabled()) {
			// Register
			task.execute(AsyncRPC.REGISTER, username, password, xtifyKey);

		} else {
			// Login
			task.execute(AsyncRPC.LOGIN, username, password, id, xtifyKey);
		}

		final Bundle args = new Bundle();
		args.putBoolean(Util.TO_LISTEN, true);
		showDialog(WAIT_DIALOG, args);
	}

	public void onCheck(View v) {
		if (userNameBox.getText().length() == 0) {
			Toast.makeText(getApplicationContext(), R.string.enter_username,
					Toast.LENGTH_SHORT).show();
		} else {
			NewTask task = new NewTask(OnlineAccount.this);
			task.execute(AsyncRPC.CHECK, userNameBox.getText().toString()
					.toLowerCase().trim());
		}

		final Bundle args = new Bundle();
		args.putBoolean(Util.TO_LISTEN, true);
		showDialog(WAIT_DIALOG, args);
	}

	class NewTask extends AsyncRPC {

		public NewTask(Context c) {
			super(c);
		}

		@Override
		protected void onPostExecute(Object result) {
			String action = getAction();
			dismissDialog(WAIT_DIALOG);

			if (action.equals(LOGIN)) {

				handleUserInteraction((UserProxy) result,
						R.string.login_failure, R.string.login_success);

			} else if (action.equals(REGISTER)) {

				handleUserInteraction((UserProxy) result,
						R.string.register_failure, R.string.register_success);

			} else if (action.equals(CHECK)) {

				Boolean b = (Boolean) result;
				int messageId = (b.booleanValue()) ? R.string.account_not_available
						: R.string.account_available;

				Toast.makeText(getApplicationContext(), getString(messageId),
						Toast.LENGTH_SHORT).show();

			} else if (action.equals(ERROR)) {

				Toast.makeText(getApplicationContext(),
						getResources().getString(R.string.error),
						Toast.LENGTH_LONG).show();
			}

		}
	}

	public void onCancel(View v) {
		finish();
	}

	private void handleUserInteraction(UserProxy user, int failureMessageId,
			int successMessageId) {

		if (user == null) {
			Toast.makeText(getApplicationContext(),
					getString(failureMessageId), Toast.LENGTH_SHORT).show();
			return;
		}

		Editor editor = prefs.edit();
		editor.putString(Util.PREF_USERID, Long.toString(user.getId()));
		editor.putString(Util.PREF_USERNAME, user.getName());
		editor.putString(Util.PREF_PASSWORD, user.getPassword());
		editor.commit();

		Toast.makeText(getApplicationContext(), getString(successMessageId),
				Toast.LENGTH_SHORT).show();

		finish();

	}

	@Override
	public void onClick(DialogInterface dialog, int which) {
		showDialog = false;

		if (which != DialogInterface.BUTTON_NEGATIVE)
			return;

		checkBtn.setEnabled(true);
		saveBtn.setText(getString(R.string.register));

	}

	// handle hard keyboard
	@Override
	public boolean onKey(View v, int keyCode, KeyEvent event) {

		final boolean isActionUp = event.getAction() == KeyEvent.ACTION_UP;
		final boolean isEnterKey = keyCode == KeyEvent.KEYCODE_ENTER;

		if (!(isActionUp && isEnterKey)) {
			return false;
		}

		final int id = v.getId();

		if (id == userNameBox.getId())
			passwordBox.requestFocus();

		if (id == passwordBox.getId())
			onSave(null);

		return true;
	}

	// Handle soft keyboard
	@Override
	public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
		if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)
			return true;

		return false;
	}

	@Override
	protected Dialog onCreateDialog(int id, Bundle args) {
		Dialog d = null;

		switch (id) {
		case (PROMPT_DIALOG):
			d = Util.buildAlertDialog(this,
					getString(R.string.login_or_register),
					getString(R.string.sign_in), this,
					getString(R.string.register), this);
			break;

		case (WAIT_DIALOG):
			OnCancelListener l = (args.getBoolean(Util.TO_LISTEN)) ? this
					: null;
			d = Util.getProgressDialog(this, R.string.please_wait, l);

			break;

		}

		return d;
	}

	@Override
	public void onCancel(DialogInterface dialog) {

		if (dialog instanceof AlertDialog) {
			finish();
		} else if (dialog instanceof ProgressDialog) {
			task.cancel(true);
		}

	}

}
